#ifndef _LIBTCPUTILS_CONNECTION_HPP_ 
#define _LIBTCPUTILS_CONNECTION_HPP_

#include <stdint.h>


namespace tcplib { 


class Buffer
{
    char *_buf;
    size_t _size;
    size_t _rpos;
    size_t _wpos;
    void check_size();
public:
    Buffer(size_t init_size = 4096);
    ~Buffer();

    void readfd(int fd);
    void readout(size_t size);


    char *rbuf() { return _buf + _rpos; }
    char *wbuf() { return _buf + _wpos; }
    size_t raw_size() { return _size; }
    size_t data_size() { return _wpos - _rpos; }
    size_t free_size() { return _size - _wpos; }
};



class Connection : public Nocopyable
{
    typedef void (*WRITTEN_FUNC)(void *, Connection *, const char*, uint32_t, int)
    typedef bool (*BOUNDCHK_FUNC)(void *, Connection *, const char *, uint32_t);
    typedef bool (*READ_FUNC)(void *, Connection *, const char *, uint32_t, int);

    static void event_handler(void *obj, int fd, int events);

private:
    EventHub *_event_hub;
    int _fd;


    struct AsyncWriteReq
    {
        const char *buf; uint32_t size;
        WRITTEN_FUNC cb;
        void *obj;
        uint32_t pos;
    };


public:
    Connection(EventHub *event_hub = NULL)
        : _event_hub(event_hub),
        _fd(NULL_FD)
    {
    }

    ~Connection()
    {
    }

    bool is_connected()
    {
        return _fd != NULL_FD;
    }

    void switch_event_hub(EventHub *event_hub);

    void connect(const char* ip_port);

    void connect(const char* ip, uint16_t port);

    void sync_connect();
    void async_connect(const InetAddr& addr);


    void set_broken_handler();
    void set_connected_handler();

    void async_write(const char *, uint32_t len, void (*written)(void *, Connection *, const char*, uint32_t, int), void *obj);

    void sync_write(const char *, uint32_t, int timeout_ms);

    void set_read_boundchecker(bool (*checker)(void *, Connection *, const char *, uint32_t), void *obj);

    void async_read(bool (*reader)(void *, Connection *, const char *, uint32_t, int), void *obj);
    void sync_read(char *, uint32_t len, int timeout_ms);
    
    uint32_t bytes_to_write();

    void close();
};



};


#endif

